/*
 * OgreMax Sample Viewer and Scene Loader - Ogre3D-based viewer and code for loading and displaying .scene files
 * Copyright 2010 AND Entertainment
 *
 * This code is available under the OgreMax Free License:
 *   -You may use this code for any purpose, commercial or non-commercial.
 *   -If distributing derived works (that use this source code) in binary or source code form, 
 *    you must give the following credit in your work's end-user documentation: 
 *        "Portions of this work provided by OgreMax (www.ogremax.com)"
 *
 * AND Entertainment assumes no responsibility for any harm caused by using this code.
 * 
 * The OgreMax Sample Viewer and Scene Loader were released at www.ogremax.com 
 */


#ifndef OgreMax_Keyboard_INCLUDED
#define OgreMax_Keyboard_INCLUDED


//Includes---------------------------------------------------------------------
#include <OIS.h>
#include "InputSource.hpp"


//Classes----------------------------------------------------------------------
namespace OgreMax
{
    /**
     * Wrapper for a keyboard device
     * All public methods are safe to call with a null device
     */
    class CPPXOIS_API Keyboard
    {
        friend class InputSystem;

        OIS::Keyboard* keyboard;

        bool updatedOnce;

        enum {KEY_COUNT = 256};
        enum {KEY_BUFFER_BYTE_SIZE = 2 * KEY_COUNT};

        /** The key buffers. There are two: one for the current update, one for the previous update */
        char keyBuffers[2][KEY_COUNT];

        /** Index of the current buffer */
        int keyBufferIndex;

        /** Pointer to the key buffer containing the keys from the most recent update */
        char* keys;

        /** Pointer to the key buffer containing the keys from the previous update */
        char* previousKeys;

    public:
        enum ModifierFlags_t
        {
            ALT_MODIFIER   = 0x1,
            CTRL_MODIFIER  = 0x2,
            SHIFT_MODIFIER = 0x4
        };

    public:
        OIS::Keyboard* GetKeyboard();

        bool IsNull() const;

        bool PressedKey(OIS::KeyCode keyCode) const;
        bool PressingKey(OIS::KeyCode keyCode) const;
        bool ReleasedKey(OIS::KeyCode keyCode) const;
        
        bool PressedAnyKey() const;
        bool PressingAnyKey() const;
        bool ReleasedAnyKey() const;

        OIS::KeyCode GetPressedKey(int* modifierFlags = 0) const;
        OIS::KeyCode GetPressingKey(int* modifierFlags = 0) const;
        OIS::KeyCode GetReleasedKey() const;

        void GetPressedKeys(InputSourceVector& inputSources) const;
        void GetPressingKeys(InputSourceVector& inputSources) const;
        void GetReleasedKeys(InputSourceVector& inputSources) const;

        static bool IsAltKey(OIS::KeyCode keyCode);
        static bool IsCtrlKey(OIS::KeyCode keyCode);
        static bool IsShiftKey(OIS::KeyCode keyCode);
        static bool IsModifierKey(OIS::KeyCode keyCode);
        static bool IsFunctionKey(OIS::KeyCode keyCode);
        static bool IsNumberKey(OIS::KeyCode keyCode);
        static int ToNumber(OIS::KeyCode keyCode);

    private:
        Keyboard();

        void Set(OIS::Keyboard* keyboard);
        void Update();
        void SetKeyBuffers(int currentKeyBufferIndex);

    //private:
    //    static bool CheckPressingAnyKey(const char* keys);
    };

}

#endif
